// CGA 8x8 font rom for IceStick
// Bruno Levy, May 2020

module FontROM(
   input wire clk,
   input wire [10:0] address,
   output wire [7:0] data
);

  wire [10:0] rom_address = {2'b00, address[9:1]};
  wire [15:0] bank1_data_16;
  wire [15:0] bank2_data_16;
  wire [15:0] bank3_data_16;
  wire [15:0] bank4_data_16;  

  SB_RAM40_4K #(
     .INIT_0(256'h000e1f3f7e3f1f0e7effebcfcfebff7e7e8195b1b195817e0000000000000000),
     .INIT_1(256'h0000183c3c1800000010b8fcfffcb8100018baffffffba1800081c3e7f3e1c08),
     .INIT_2(256'h0f077ffd8888f870ffc399bdbd99c3ff003c664242663c00ffffe7c3c3e7ffff),
     .INIT_3(256'h995a3ce7e73c5a993f7f6505057fffc0070705057fffe0c0004e5ff1f15f4e00),
     .INIT_4(256'h005f5f00005f5f00002466ffff662400007f3e3e1c1c08080008081c1c3e3e7f),
     .INIT_5(256'h8094b6ffffb694800070707070707000020359fda5bfda407f7f017f7f090f06),
     .INIT_6(256'h000808082a3e1c0800081c3e2a0808080010307f7f3010000004067f7f060400),
     .INIT_7(256'h060e1e3e3e1e0e0630383c3e3e3c3830081c3e08083e1c080020202020203c3c),
     .INIT_8(256'h00147f7f147f7f140000070700070700000000065f5f06000000000000000000),
     .INIT_9(256'h000000000003070400487a375d4f7a300062660c183066460000123a6b6b2e24),
     .INIT_A(256'h000008083e3e0808082a3e1c1c3e2a080000001c3e63410000000041633e1c00),
     .INIT_B(256'h000103060c183060000000006060000000000808080808080000000060e08000),
     .INIT_C(256'h0000367f494963220000666f49597362000040407f7f4240003e7f4d59717f3e),
     .INIT_D(256'h0000070f7971030300003079494b7e3c0000397d4545672700507f7f53161c18),
     .INIT_E(256'h0000000066e68000000000006666000000001e3f69494f060000367f49497f36),
     .INIT_F(256'h0000060f595103020000081c3663410000002424242424240000004163361c08)
  ) bank1(
     .RADDR(rom_address),
     .RDATA(bank1_data_16),
     .RE(address[10:9] == 2'b00),
     .RCLK(clk),
     .RCLKE(1'b1),
  );

  SB_RAM40_4K #(
     .INIT_0(256'h0022634141633e1c00367f49497f7f4100007c7e13137e7c001e1f5d5d417f00),
     .INIT_1(256'h0072735141633e1c0003011d497f7f410063415d497f7f41001c3e63417f7f41),
     .INIT_2(256'h0063771c087f7f4100013f7f41407030000000417f7f410000007f7f08087f7f),
     .INIT_3(256'h001c3e6341633e1c007f7f180c067f7f007f7f0e1c0e7f7f00706040417f7f41),
     .INIT_4(256'h00003273594d6f2600667f19097f7f4100005e7f71213f1e00060f09497f7f41),
     .INIT_5(256'h007f7f3018307f7f00001f3f60603f1f00007f7f40407f7f000003417f7f4103),
     .INIT_6(256'h00000041417f7f000073674d597163470000074f78784f070043673c183c6743),
     .INIT_7(256'h808080808080808000080c0603060c080000007f7f414100006030180c060301),
     .INIT_8(256'h0000286c44447c3800307848483f7f410040783c545474200000000407030000),
     .INIT_9(256'h00047cf8a4a4bc9800000203497f7e480000185c54547c3800407f3f49487830),
     .INIT_A(256'h00446c38107f7f4100007dfd8080e060000000407d7d440000787c04087f7f41),
     .INIT_B(256'h0000387c44447c380000787c04047c7c00787c1c38187c7c000000407f7f4100),
     .INIT_C(256'h0000247454545c4800181c044c787c440084fcf8a4243c1800183c24a4f8fc84),
     .INIT_D(256'h003c7c7038707c3c00001c3c60603c1c00407c3c40407c3c000024447f3e0400),
     .INIT_E(256'h00004141773e08080000644c5c74644c00007cfca0a0bc9c00446c3810386c44),
     .INIT_F(256'h0070784c464c78700001030203010302000008083e7741410000007777000000)
  ) bank2(
     .RADDR(rom_address),
     .RDATA(bank2_data_16),
     .RE(address[10:9] == 2'b01),
     .RCLK(clk),
     .RCLKE(1'b1),
  );

  SB_RAM40_4K #(
     .INIT_0(256'h427b7d55557523020000195d55547c3800407a7a40407a3a00004afbb1919f00),
     .INIT_1(256'h000040e4a4a43c180040787c575774200040787c545575210040797d54547521),
     .INIT_2(256'h000001417c7c45010000185c54557d390000195d54547d39021b5d55557d3b02),
     .INIT_3(256'h000070782b2b787000797d1612167d79000000407c7d45010002437d7d450302),
     .INIT_4(256'h0000327b49497b3200497f7f090b7e7c54547c7c5454742000004555557c7c44),
     .INIT_5(256'h0040787840427a3a00407a7b41417b3a00003078484a7a320000327a48487a32),
     .INIT_6(256'h002424e7e7243c1800003d7d40407d3d01193c66663c190100007afaa0a0ba9a),
     .INIT_7(256'h0203097ffe88c040a0f8f62f0909ffff00002b2ffcfc2f2b00206643497f7e68),
     .INIT_8(256'h00407a7a424078380000327a4a487830000000417d7d44000040797d55547420),
     .INIT_9(256'h0000262f292f260000282f2f292f260000007d7d31197d7d0000707a0a0a7a7a),
     .INIT_A(256'h91bbeecc18306f4f0000383808080808000008080808383800002060454d7830),
     .INIT_B(256'h081c3622081c362222361c0822361c080000007b7b000000f9fb766c18306f4f),
     .INIT_C(256'h000000ffff00000077ffaadd77aaffdd55aa55aa55aa55aa005500aa005500aa),
     .INIT_D(256'h00f0f010f0f0101000ffff00ffff1010000000ffff141414000000ffff101010),
     .INIT_E(256'h00fcfc04f4f4141400ffff00ffff000000ffff00f7f71414000000fcfc141414),
     .INIT_F(256'h000000f0f01010100000001f1f141414001f1f101f1f1010001f1f1017171414)
  ) bank3(
     .RADDR(rom_address),
     .RDATA(bank3_data_16),
     .RE(address[10:9] == 2'b10),
     .RCLK(clk),
     .RCLKE(1'b1),
  );

  SB_RAM40_4K #(
     .INIT_0(256'h101010ffff000000101010f0f01010101010101f1f1010101010101f1f000000),
     .INIT_1(256'h10ffff00ffff0000141414ffff000000101010ffff1010101010101010101010),
     .INIT_2(256'h14f4f404f4f41414141717101717141414f4f404fcfc0000141717101f1f0000),
     .INIT_3(256'h141414171714141414f7f700f7f71414141414141414141414f7f700ffff0000),
     .INIT_4(256'h101f1f101f1f000010f0f010f0f01010141414f4f4141414101f1f101f1f1010),
     .INIT_5(256'h10ffff10ffff101010f0f010f0f00000141414fcfc0000001414141f1f000000),
     .INIT_6(256'hffffffffffffffff101010f0f00000000000001f1f101010141414ffff141414),
     .INIT_7(256'h0f0f0f0f0f0f0f0fffffffff0000000000000000fffffffff0f0f0f0f0f0f0f0),
     .INIT_8(256'h00027e7e027e7e020000060602027e7e0000143e2a2afefc00446c386c447c38),
     .INIT_9(256'h0002067c7e020604001e3e20207efe800004043c7c447c3800006363495d7763),
     .INIT_A(256'h0000397d4f4a7830004c7e7301737e4c001c3e6b496b3e1c000099bde7e7bd99),
     .INIT_B(256'h00007e7f01017f7e00000049496b3e1c183d273e3c64fc98183c243c3c243c18),
     .INIT_C(256'h000040515b4e4440000040444e5b5140000044445f5f444400002a2a2a2a2a2a),
     .INIT_D(256'h0012362436123624000008086b6b08080000007fff80e060060701fffe000000),
     .INIT_E(256'h0101ffffc0703010000000101000000000000018180000000000060f090f0600),
     .INIT_F(256'h000000000000000000003c3c3c3c000000000012171d190000001e1f011f1f00)
  ) bank4(
     .RADDR(rom_address),
     .RDATA(bank4_data_16),
     .RE(address[10:9] == 2'b11),
     .RCLK(clk),
     .RCLKE(1'b1),
  );

  // Why can't I do a big OR between the four bankn_data_16 ?
  // wire [15:0]  data_16 = bank1_data_16 | bank2_data_16 | bank3_data_16 | bank4_data_16;
  // Anyway, it would not work, because RE(1'b0) does not ensure that read data is 0....

  wire [15:0]  data_16 = 
      address[10:9] == 2'b00 ? bank1_data_16 :
      address[10:9] == 2'b01 ? bank2_data_16 :
      address[10:9] == 2'b10 ? bank3_data_16 :
      address[10:9] == 2'b11 ? bank4_data_16 : 16'd0 ;

  assign data = address[0] ? data_16[15:8] : data_16[7:0];

endmodule


